from flask import Flask, request
import json
from Resp import Resp
import PanTools
from UserRedis import UserRedis
from HouseRedis import HouseRedis
from ReqRedis import ReqRedis
import OSS
import time
from flask_socketio import SocketIO, join_room, leave_room, send, emit

app = Flask(__name__)
socketio = SocketIO(app, cors_allowed_origins="*")

app.config['REDIS_HOST'] = "127.0.0.1"  # redis数据库地址
app.config['REDIS_PORT'] = 6379  # redis 端口号
app.config['REDIS_HOUSE_DB'] = 0  # 数据库名
app.config['REDIS_USER_DB'] = 1  # 数据库名
app.config['REDIS_REQ_DB'] = 2  # 数据库名
app.config['REDIS_EXPIRE'] = 60 * 60 * 24  # redis 过期时间60秒

@app.route('/api/queryHouse', methods=['POST'])
def queryHouse():
    print(request.form)

    houseId = request.form.get("id")
    name = request.form.get("name")
    password = request.form.get("password")
    openId = request.form.get("openId")

    if len(houseId) > 10 or len(name) > 6 or len(password) > 10:
        return Resp.fail('数据输入有误')

    houseInfo = HouseRedis.hgetall(houseId)

    print(houseInfo)
    t = str(int(time.time()))

    if not houseInfo:
        print("创建房间")
        HouseRedis.hset(houseId, 'id', houseId)
        HouseRedis.hset(houseId, 'password', password)
        HouseRedis.hset(houseId, 'path', '-1')
        HouseRedis.hset(houseId, 'owner', openId)

        t = str(int(time.time()))
        partner = {}
        user = {"openId": openId, "name": name, 'control': True, 'time': t}
        partner[openId] = user
        HouseRedis.hset(houseId, 'partner', json.dumps(partner))
        # status = {'status': 0, 'time': 200, "uptime": second}
        status = {'isPlay': 0, "time": 0, "uptime": 0}
        HouseRedis.hset(houseId, 'status', json.dumps(status))
        HouseRedis.hset(houseId, 'isAutoFalse', '1')
        HouseRedis.hset(houseId, 'opeTime', 0)

        HouseRedis.expire(houseId)

        return Resp.success(0)  # 0 表示房间创建成功，用户应该跳转至网盘页面
    else:
        housePassword = houseInfo.get('password')
        housePath = houseInfo.get('path')
        owner = houseInfo.get('owner')

        respFlag = 0
        if housePassword == password:
            if housePath == '-1':
                if owner == openId:
                    respFlag = 1
                else:
                    return Resp.fail("房主还未选片")
            else:
                if owner == openId:
                    respFlag = 2
                else:
                    respFlag = 3
            return Resp.success(respFlag)
        else:
            return Resp.fail("密码错误")


@app.route('/api/isLogin', methods=['POST'])
def isLogin():
    openId = request.form.get("openId")
    houseId = request.form.get("houseId")
    password = request.form.get("password")

    if HouseRedis.hget(houseId, 'password') != password:
        return Resp.fail("密码错误")

    if HouseRedis.hget(houseId, 'owner') != openId:
        return Resp.fail("您不是房主")

    accessToken = HouseRedis.hget(houseId, 'accessToken')

    if accessToken is not None:
        return Resp.success("已登录")
    else:
        return Resp.fail("未登录")


@app.route('/api/getLoginCode', methods=['POST'])
def getLoginCode():
    openId = request.form.get("openId")
    houseId = request.form.get("houseId")
    password = request.form.get("password")

    if HouseRedis.hget(houseId, 'password') != password:
        return Resp.fail("密码错误")

    if HouseRedis.hget(houseId, 'owner') != openId:
        return Resp.fail("您不是房主")

    resp = PanTools.getLoginCode()
    print(resp)
    if resp == None:
        return Resp.fail("错误")

    res = json.loads(resp)

    device_code = res['device_code']
    qrcode_url = res['qrcode_url']

    UserRedis.hset(openId, 'deviceCode', device_code)

    return Resp.success(qrcode_url)


@app.route('/api/checkLoginStatus', methods=['POST'])
def checkLoginStatus():
    openId = request.form.get("openId")
    houseId = request.form.get("houseId")
    password = request.form.get("password")

    if HouseRedis.hget(houseId, 'password') != password:
        return Resp.fail("密码错误")

    if HouseRedis.hget(houseId, 'owner') != openId:
        return Resp.fail("您不是房主")

    deviceCode = UserRedis.hget(openId, 'deviceCode')

    resp = PanTools.checkLoginStatus(deviceCode)
    print(resp)
    if resp == None:
        return Resp.fail("错误")

    res = json.loads(resp)
    if 'error' not in res:
        accessToken = res['access_token']
        HouseRedis.hset(houseId, 'accessToken', accessToken)
        return Resp.success('登录成功')
    else:
        errorMsg = res['error']
        if errorMsg == 'authorization_pending':
            return Resp.fail('还未成功')
        if errorMsg == 'slow_down':
            return Resp.fail('请稍后，两次查询不能小于五秒')
        if errorMsg == 'invalid_grant':
            return Resp.fail('请重新进入')
    return Resp.fail('奇怪的分支')


@app.route('/api/getFileList', methods=['POST'])
def getFileList():
    openId = request.form.get("openId")
    path = request.form.get("path")
    houseId = request.form.get("houseId")
    password = request.form.get("password")

    if HouseRedis.hget(houseId, 'password') != password:
        return Resp.fail("密码错误")

    if HouseRedis.hget(houseId, 'owner') != openId:
        return Resp.fail("您不是房主")

    accessToken = HouseRedis.hget(houseId, 'accessToken')

    res = PanTools.filelist(accessToken, path)
    return res


@app.route('/api/playCurrentVideo', methods=['POST'])
def playCurrentVideo():
    openId = request.form.get("openId")
    path = request.form.get("path")
    houseId = request.form.get("houseId")
    password = request.form.get("password")
    adToken = request.form.get("adToken")

    if HouseRedis.hget(houseId, 'password') != password:
        return Resp.fail("密码错误")

    if HouseRedis.hget(houseId, 'owner') != openId:
        return Resp.fail("您不是房主")

    accessToken = HouseRedis.hget(houseId, 'accessToken')

    if adToken != None:
        res1080 = PanTools.getm3u8(
            access_token=accessToken, path=path, type=2, adToken=adToken)
    else:
        res1080 = PanTools.getm3u8(
            access_token=accessToken, path=path, type=2, adToken=adToken)

    if res1080 == None:
        return Resp.fail('失败')
    if res1080.get('err') == 1:
        return res1080

    res720 = PanTools.getm3u8(access_token=accessToken,
                              path=path, type=1, adToken=adToken)
    res480 = PanTools.getm3u8(access_token=accessToken,
                              path=path, type=0, adToken=adToken)

    t = str(int(time.time()))

    totalTime = PanTools.getTotalTime(res1080.get('res'))

    if totalTime == None:
        return Resp.fail('时长获取失败')

    url1080 = OSS.upload(t, res1080.get('res'), "1080")
    url720 = OSS.upload(t, res720.get('res'), "720")
    url480 = OSS.upload(t, res480.get('res'), "480")

    if url1080 == None:
        return Resp.fail('失败')

    HouseRedis.hset(houseId, 'path', path)
    videoName = path.split('/')[-1].split('.')[-2]
    HouseRedis.hset(houseId, 'videoName', videoName)
    HouseRedis.hset(houseId, 'totalTime', totalTime)
    HouseRedis.hset(houseId, 'url1080', url1080)
    HouseRedis.hset(houseId, 'url720', url720)
    HouseRedis.hset(houseId, 'url480', url480)
    status = {'isPlay': 0, "time": 0, "uptime": 0}
    HouseRedis.hset(houseId, 'status', json.dumps(status))

    return Resp.success(url1080)


@app.route('/api/getCurrentVideo', methods=['POST'])
def getCurrentVideo():
    houseId = request.form.get("houseId")
    password = request.form.get("password")
    type = request.form.get("type")

    if HouseRedis.hget(houseId, 'password') != password:
        return Resp.fail("密码错误")

    url = ''
    if type == '1080':
        url = HouseRedis.hget(houseId, 'url1080')
    if type == '720':
        url = HouseRedis.hget(houseId, 'url720')
    if type == '480':
        url = HouseRedis.hget(houseId, 'url480')

    videoName = HouseRedis.hget(houseId, 'videoName')
    owner = HouseRedis.hget(houseId, 'owner')
    status = json.loads(HouseRedis.hget(houseId, 'status'))
    opeTime = int(HouseRedis.hget(houseId, 'opeTime'))
    totalTime = int(HouseRedis.hget(houseId, 'totalTime'))
    isAutoFalse = HouseRedis.hget(houseId, 'isAutoFalse')

    return Resp.success({'videoName': videoName, 'url': url, 'status': status, 'opeTime': opeTime, 'owner': owner, 'totalTime': totalTime, 'isAutoFalse': isAutoFalse == '1'})


@app.route('/api/getVideoStatus', methods=['POST'])
def getVideoStatus():
    houseId = request.form.get("houseId")
    password = request.form.get("password")
    openId = request.form.get("openId")

    if HouseRedis.hget(houseId, 'password') != password:
        return Resp.fail("密码错误")

    partner = json.loads(HouseRedis.hget(houseId, 'partner'))
    owner = HouseRedis.hget(houseId, 'owner')
    user = partner.get(openId)
    if owner != openId:
        if user == None:
            return Resp.fail('不属于该房间')

    status = json.loads(HouseRedis.hget(houseId, 'status'))
    opeTime = int(HouseRedis.hget(houseId, 'opeTime'))

    return Resp.success({'status': status, 'opeTime': opeTime, 'owner': owner})


@app.route('/api/changeControl', methods=['POST'])
def changeControl():
    houseId = request.form.get("houseId")
    password = request.form.get("password")
    openId = request.form.get("openId")
    userOpenId = request.form.get("userOpenId")

    if HouseRedis.hget(houseId, 'password') != password:
        return Resp.fail("密码错误")

    partner = json.loads(HouseRedis.hget(houseId, 'partner'))
    owner = HouseRedis.hget(houseId, 'owner')
    user = partner.get(userOpenId)

    if owner != openId:
        return Resp.fail("您不是房主")

    if userOpenId == openId:
        return Resp.fail("不可以改变自己的状态")

    if user == None:
        return Resp.fail('用户不在房间内')

    control = not user['control']
    user['control'] = control

    partner[userOpenId] = user
    HouseRedis.hset(houseId, 'partner', json.dumps(partner))

    return Resp.success(control)


@app.route('/api/changeAutoFalse', methods=['POST'])
def changeAutoFalse():
    houseId = request.form.get("houseId")
    password = request.form.get("password")
    openId = request.form.get("openId")

    if HouseRedis.hget(houseId, 'password') != password:
        return Resp.fail("密码错误")

    owner = HouseRedis.hget(houseId, 'owner')

    if owner != openId:
        return Resp.fail("您不是房主")

    control = HouseRedis.hget(houseId, 'isAutoFalse')
    control = '1' if control == '0' else '0'
    HouseRedis.hset(houseId, 'isAutoFalse', control)

    return Resp.success(control == '1')


@app.route('/api/getBackChoose', methods=['POST'])
def getBackChoose():
    houseId = request.form.get("houseId")
    password = request.form.get("password")
    openId = request.form.get("openId")

    if HouseRedis.hget(houseId, 'password') != password:
        return Resp.fail("密码错误")

    if HouseRedis.hget(houseId, 'owner') != openId:
        return Resp.fail("您不是房主")

    t = str(int(time.time()))
    HouseRedis.hset(houseId, 'path', '-1')
    HouseRedis.hset(houseId, 'uptime', t)

    return Resp.success("成功")


@app.route('/api/getPartner', methods=['POST'])
def getPartner():
    houseId = request.form.get("houseId")
    password = request.form.get("password")

    if HouseRedis.hget(houseId, 'password') != password:
        return Resp.fail("密码错误")

    partner = json.loads(HouseRedis.hget(houseId, 'partner'))
    print(partner)
    return Resp.success(partner)


namespace = '/socket'


@socketio.on('connect', namespace=namespace)
def connect():
    print('用户连接')


@socketio.on('disconnect', namespace=namespace)
def disconnect():
    sid = request.sid
    openId = ReqRedis.read(sid)

    userName = UserRedis.hget(openId, 'name')
    houseId = UserRedis.hget(openId, 'house')

    partner = json.loads(HouseRedis.hget(houseId, 'partner'))
    del partner[openId]
    leave_room(room=houseId, sid=sid, namespace=namespace)
    HouseRedis.hset(houseId, 'partner', json.dumps(partner))

    emit('leaveUser', {'openId': openId, 'name': userName},
         namespace=namespace, room=houseId)

    print("用户断开")


@socketio.on('changeTime', namespace=namespace)
def changeTime(data):
    houseId = data.get("houseId")
    password = data.get("password")
    openId = data.get("openId")
    status = data.get("status")

    if HouseRedis.hget(houseId, 'password') != password:
        return Resp.fail("密码错误")

    partner = json.loads(HouseRedis.hget(houseId, 'partner'))
    owner = HouseRedis.hget(houseId, 'owner')
    user = partner.get(openId)
    if owner != openId:
        if user == None:
            return Resp.fail('不属于该房间')
    control = user['control']
    if control != True:
        emit('changeMsg', Resp.fail('您没有权限'),
             namespace=namespace, room=houseId, to=request.sid)
        return

    opeTime = int(HouseRedis.hget(houseId, 'opeTime'))
    opeTime += 1

    statusTemp = json.loads(status)

    HouseRedis.hset(houseId, 'status', status)
    HouseRedis.hset(houseId, 'opeTime', opeTime)

    status = json.loads(HouseRedis.hget(houseId, 'status'))
    resp = {'status': status, 'opeTime': opeTime,
            'except': openId, 'name': UserRedis.hget(openId, 'name')}
    print('time changed from user' + UserRedis.hget(openId, 'name'))

    emit('changeMsg', Resp.success(opeTime),
         namespace=namespace, room=houseId, to=request.sid)

    emit('timeChanged', resp,
         namespace=namespace, room=houseId)


@socketio.on('userJoin', namespace=namespace)
def on_join(data):
    print(request.sid)
    print(data)

    houseId = data['houseId']
    openId = data['openId']
    password = data['password']
    userName = data['name']

    if HouseRedis.hget(houseId, 'password') != password:
        emit('joinBack', Resp.fail(
            '密码错误'), namespace=namespace, broadcast=False, to=request.sid)
        return

    ReqRedis.write(request.sid, openId)

    partner = dict(json.loads(HouseRedis.hget(houseId, 'partner')))
    user = partner.get(openId)
    isAutoFalse = HouseRedis.hget(houseId, 'isAutoFalse')
    owner = HouseRedis.hget(houseId, 'owner')
    t = str(int(time.time()))
    if openId == owner:
        user = {"openId": openId, 'name': userName,
                'control': True, 'time': t}
    else:
        user = {"openId": openId, 'name': userName,
                'control': isAutoFalse == '0', 'time': t}
    partner[openId] = user
    UserRedis.hset(openId, 'openId', openId)
    UserRedis.hset(openId, 'name', userName)
    UserRedis.hset(openId, 'house', houseId)
    UserRedis.expire(openId)
    HouseRedis.hset(houseId, 'partner', json.dumps(partner))

    emit('joinBack', Resp.success(
        1), namespace=namespace, broadcast=False, to=request.sid)

    join_room(houseId, namespace=namespace)

    isAutoFalse = HouseRedis.hget(houseId, 'isAutoFalse')

    emit('newUser', {'openId': openId, 'name': userName,
         'control': isAutoFalse == '0'}, namespace=namespace, room=houseId)


@socketio.on('backTo', namespace=namespace)
def backTo(data):
    houseId = data['houseId']
    openId = data['openId']
    password = data['password']

    if HouseRedis.hget(houseId, 'password') != password:
        return

    owner = HouseRedis.hget(houseId, 'owner')
    if owner != openId:
        return

    emit('videoChanging', Resp.success(1), namespace=namespace, room=houseId)


@socketio.on('changeVideo', namespace=namespace)
def changeVideo(data):
    houseId = data['houseId']
    openId = data['openId']
    password = data['password']

    if HouseRedis.hget(houseId, 'password') != password:
        return

    owner = HouseRedis.hget(houseId, 'owner')
    if owner != openId:
        return

    emit('videoChanged', Resp.success(1), namespace=namespace, room=houseId)


@socketio.on('sendDanmu', namespace=namespace)
def sendDanmu(data):
    houseId = data['houseId']
    value = data['value']
    color = data['color']
    openId = data['openId']
    password = data['password']
    userName = UserRedis.hget(openId, 'name')

    if HouseRedis.hget(houseId, 'password') != password:
        return

    emit('updateDanmu', {'value': value, 'color': color, 'name': userName, 'openId': openId},
         namespace=namespace, room=houseId)


if __name__ == '__main__':
    # app.run(debug=True)
    socketio.run(app, host='127.0.0.1', port=5000, debug=True, log_output=True)
